package com.nchu.ft.common.exception.handler;

import com.nchu.ft.common.constant.ApiCodeConstant;
import com.nchu.ft.common.domain.ApiResult;
import com.nchu.ft.common.exception.MyException;
import com.nchu.ft.common.exception.file.FileNotExistException;
import com.nchu.ft.common.exception.file.NullStorageConfigurationException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.List;

/**
 * @className: GlobalExceptionHandler
 * @description: 全局异常处理器
 * @author: Li Chuanwei
 * @date: 2024/01/18 11:11
 * @Company: Copyright [日期] by [作者或个人]
 **/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public ApiResult<String> nullPointerExceptionHandler(NullPointerException ex)
    {
        log.error(ex.getMessage(),ex);
        return ApiResult.fail(ApiCodeConstant.RESULT_NULLPOINT_EXCEPTION, ex.toString());
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ApiResult<String> httpRequestMethodNotSupportedHandleR(HttpRequestMethodNotSupportedException ex,
                                                          HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',不支持'{}'请求", requestURI, ex.getMethod());
        System.out.println(requestURI);
        return ApiResult.fail(ApiCodeConstant.RESULT_METHODNOTSUPPORTED_EXCEPTION,ex.getMessage());
    }

    /**
     * 请求路径中缺少必需的路径变量
     */
    @ExceptionHandler(MissingPathVariableException.class)
    public ApiResult<String> missingPathVariableExceptionHandler(MissingPathVariableException e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
        return ApiResult.fail(ApiCodeConstant.RESULT_MISSINGPATHVARIABLE_EXCEPTION,String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
    }

    /**
     * 请求参数类型不匹配
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ApiResult<String> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException e,
                                                                HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
        return ApiResult.fail(ApiCodeConstant.RESULT_METHODARGUMENTTYPEMISMATCH_EXCEPTION,String.format("请求参数类型不匹配，参数[%s]要求类型为：'%s'，但输入值为：'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
    }

    /**
     * 控制器参数校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResult<String> handleValidationException(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();
        StringBuilder errorMessageLogBuilder = new StringBuilder();
        StringBuilder errorMessageBuilder = new StringBuilder();

        for (FieldError fieldError : fieldErrors) {
            String fieldName = fieldError.getField();
            String errorMessage = fieldError.getDefaultMessage();
            // 获取声明验证错误的类
            String declaringClass = fieldError.getObjectName();
            errorMessageLogBuilder.append(declaringClass)
                    .append(".")
                    .append(fieldName)
                    .append(": ")
                    .append(errorMessage)
                    .append(", ");

            errorMessageBuilder.append(fieldName)
                    .append(": ")
                    .append(errorMessage)
                    .append(", ");
        }

        log.error("参数校验异常异常：'{}'", errorMessageLogBuilder.toString());

        return ApiResult.fail(ApiCodeConstant.RESULT_METHODARGUMENTNOTVALID_EXCEPTION, errorMessageBuilder.toString());
    }

    /**
     * 配置参数为空异常
     */
    @ExceptionHandler(NullStorageConfigurationException.class)
    public ApiResult<String> nullStorageConfigurationExceptionHandler(NullStorageConfigurationException ex)
    {
        log.error(ex.getDefaultMessage(),ex);
        return ApiResult.fail(ex.getCode(), ex.getDefaultMessage());
    }

    /**
     * 文件不存在异常
     */
    @ExceptionHandler(FileNotExistException.class)
    public ApiResult<String> fileNotFoundExceptionHandler(FileNotExistException ex)
    {
        log.error(ex.getDefaultMessage(),ex);
        return ApiResult.fail(ex.getCode(), ex.getDefaultMessage());
    }


    /**
     * 自定义异常
     */
    @ExceptionHandler(MyException.class)
    public ApiResult<String> myExceptionHandler(Exception ex) {
        log.error("自定义异常：'{}'",ex.getMessage(), ex);
        return  ApiResult.fail(((MyException)ex).getCode(), ex.getMessage());
    }

    /**
     * 其他未知异常
     */
    @ExceptionHandler(Exception.class)
    public ApiResult<String> otherExceptionHandler(Exception ex) {
        log.error(ex.getMessage(), ex);
        return  ApiResult.fail(ApiCodeConstant.RESULT_OTHER_EXCEPTION, ex.toString());
    }
}
